/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhangpu
 * date:2016年4月4日
 *
 */
package com.acooly.module.openapi.client.provider.fuyou.marshall;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.core.utils.validate.Validators;
import com.acooly.module.openapi.client.api.anotation.ApiItem;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.provider.fuyou.FuyouConstants;
import com.acooly.module.openapi.client.provider.fuyou.OpenAPIClientFuyouProperties;
import com.acooly.module.openapi.client.provider.fuyou.domain.FuyouApiMessage;
import com.acooly.module.openapi.client.provider.fuyou.domain.FuyouRequest;
import com.acooly.module.openapi.client.provider.fuyou.enums.FuyouServiceEnum;
import com.acooly.module.openapi.client.provider.fuyou.support.FuyouAlias;
import com.acooly.module.safety.Safes;
import com.acooly.module.safety.signature.SignerFactory;
import com.acooly.module.safety.support.KeyPair;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

/**
 * @author zhangpu
 */
@Slf4j
public class FuyouMarshallSupport {

    protected static final char SPLIT_CHAR = '|';

    @Autowired
    protected OpenAPIClientFuyouProperties openAPIClientFuiouProperties;

    @Autowired
    protected SignerFactory signerFactory;

    private KeyPair keyPair;

    public void setSignerFactory(SignerFactory signerFactory) {
        this.signerFactory = signerFactory;
    }

    public SignerFactory getSignerFactory() {
        return signerFactory;
    }

    protected String getWaitForSign(Map<String, String> message) {
        Map<String, String> treeMap = Maps.newTreeMap();
        for (Map.Entry<String, String> entry : message.entrySet()) {
            if (Strings.equals(openAPIClientFuiouProperties.getSignatrueParamKey(), entry.getKey()) || Strings.equals("resp_desc", entry.getKey())) {
                continue;
            }
            treeMap.put(entry.getKey(), entry.getValue());
        }
        StringBuilder sb = new StringBuilder();
        for (String v : treeMap.values()) {
            sb.append(Strings.trimToEmpty(v)).append(SPLIT_CHAR);
        }
        String waitForSign = sb.substring(0, sb.length() - 1);
        return waitForSign;
    }

    protected void beforeMarshall(FuyouApiMessage message) {
        message.setPartner(openAPIClientFuiouProperties.getPartnerId());
    }

    /**
     * 签名 优先获取传进来的，如果传进来没有则用配置文件中的
     *
     * @param waitForSign
     * @return
     */
    protected String doSign(String waitForSign, String serviceKey) {
        String key = getSignKey(serviceKey);
        if(!FuyouServiceEnum.FUYOU_WITHDRAW_QUERY.equals(FuyouServiceEnum.find(serviceKey)) && !FuyouServiceEnum.FUYOU_WITHDRAW.equals(FuyouServiceEnum.find(serviceKey))) {
            waitForSign = waitForSign + key;
        }
        String signStr = Safes.getSigner(FuyouConstants.MD5_SIGN_TYPE).sign(waitForSign, key);
        return signStr;
    }

    protected OpenAPIClientFuyouProperties getProperties() {
        return openAPIClientFuiouProperties;
    }

    /**
     * 验签 优先获取传进来的，如果传进来没有则用配置文件中的
     *
     * @param waitForSign
     * @return
     */
    protected void doVerify(String waitForSign, String signNature, String serviceKey) {
        String key = getSignKey(serviceKey);
        if(!FuyouServiceEnum.FUYOU_WITHDRAW_QUERY.equals(FuyouServiceEnum.find(serviceKey)) && !FuyouServiceEnum.FUYOU_WITHDRAW.equals(FuyouServiceEnum.find(serviceKey))) {
            waitForSign = waitForSign + key;
        }
        Safes.getSigner(FuyouConstants.MD5_SIGN_TYPE).verify(waitForSign, key, signNature);
        log.info("验签成功");
    }

    /**
     * 校验参数
     *
     * @param source
     */
    protected void doVerifyParam(FuyouApiMessage source) {
        try {
            source.doCheck();
            Validators.assertJSR303(source);
        } catch (Exception e) {
            throw new ApiClientException(e.getMessage());
        }
    }

    /**
     * 获取代签map
     *
     * @param source
     * @return
     */
    protected Map<String, String> getRequestDataMap(FuyouRequest source) {
        Map<String, String> requestData = Maps.newTreeMap();
        Set<Field> fields = Reflections.getFields(source.getClass());
        String key = null;
        Object value = null;
        for (Field field : fields) {
            value = Reflections.getFieldValue(source, field.getName());
            if (value == null) {
                continue;
            }
            FuyouAlias fuyouAlias = field.getAnnotation(FuyouAlias.class);
            if (fuyouAlias == null) {
                key = field.getName();
            } else {
                if (!fuyouAlias.sign()) {
                    continue;
                }
                key = fuyouAlias.value();
                if (Strings.isBlank(key)) {
                    key = field.getName();
                }
            }
            if (Strings.isNotBlank((String) value)) {
                requestData.put(key, (String) value);
            }
        }
        return requestData;
    }

    /**
     * 根据服务类型区分密钥
     *
     * @param serviceKey
     * @return
     */
    public String getSignKey(String serviceKey) {
        if (FuyouServiceEnum.FUYOU_NETBANK.equals(FuyouServiceEnum.find(serviceKey)) || FuyouServiceEnum.FUYOU_NETBANK_SYNCHRO_QUERY.equals(FuyouServiceEnum.find(serviceKey)) ||
                FuyouServiceEnum.FUYOU_WITHDRAW_QUERY.equals(FuyouServiceEnum.find(serviceKey)) || FuyouServiceEnum.FUYOU_WITHDRAW.equals(FuyouServiceEnum.find(serviceKey))) {
            return openAPIClientFuiouProperties.getNetbankMd5Key();
        } else {
            return openAPIClientFuiouProperties.getQuickMd5Key();
        }
    }

}
